function parseHtmlToAst(html) {

    // Regular Expressions for parsing tags and attributes
    const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
    const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`
    const qnameCapture = `((?:${ncname}\\:)?${ncname})`
    const startTagOpen = new RegExp(`^<${qnameCapture}`)
    const startTagClose = /^\s*(\/?)>/
    const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)

    let root,
        currentParent,
        stack = [];

    while (html) {
        const textEnd = html.indexOf('<');
        if(textEnd === 0) {
            const startTagMatch = parseStartTag();
            if(startTagMatch) {
                start(startTagMatch.tag, startTagMatch.attrs);
                continue;
            }

            const endTagMatch = html.match(endTag);
            if(endTagMatch) {
                end();
                advance(endTagMatch[0].length);
                continue;
            }
        }
        if(textEnd > 0) {
            chars(html.slice(0, textEnd));
            advance(textEnd);
        }
    }
    return root;
    // stack[div, span]
    /*>
        <span style="color: #999; font-size: 20px;">{{title}}</span>
        我出现了 {{ infos.date }}
    </div>*/

    function parseStartTag() {
        const start = html.match(startTagOpen);
        if (start) {
            advance(start[0].length);
            const match = {
                tag: start[1],
                attrs: []
            }
            let end,
                attr;
            while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
                match.attrs.push({
                    name: attr[1],
                    value: attr[3] || attr[4] || attr[5]
                })
                advance(attr[0].length);
            }
            if(end) {
                advance(end[0].length);
            }
            return match;
        }
    }
    function advance(index) {
        html = html.substring(index);
    }
    function tagInfo(tag, attrs) {
        return {
            type: 1,
            tag,
            attrs,
            children: [],
            parent
        }
    }
    function start(tag, attrs) {
        const tagNode = tagInfo(tag, attrs);
        if(!root) {
            root = tagNode;
        }
        currentParent = tagNode;
        stack.push(tagNode);
    }
    function end() {
        const tagNode = stack.pop();
        currentParent = stack[stack.length - 1];
        if(currentParent) {
            tagNode.parent = currentParent;
            currentParent.children.push(tagNode);
        }
    }
    function chars(text) {
        text = text.trim();
        if(text) {
            currentParent.children.push({
                type: 3,
                text,
                parent: currentParent
            })
        }
    }
}

export {
    parseHtmlToAst
}